package io.terminus.paas.profiler.service.impl

import io.terminus.paas.profiler.model.TracingRecord
import io.terminus.paas.profiler.service.MonitorService
import org.influxdb.InfluxDBFactory
import org.influxdb.dto.Query
import org.springframework.stereotype.Service
import java.text.SimpleDateFormat
import java.util.*

/**
 * Created by gengrong on 16/4/5.
 */
@Service
class MonitorServiceInFluxDBImpl : MonitorService {
    private val dataBase = "pampas_profiler_monitor";

    private val isoDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")

    private val influxDB = InfluxDBFactory.connect("http://192.168.0.251:8086", "root", "root");

    private val selectFields = "select time,rootId,parentId,tracingId,interfaceName,methodName,status,executionTime";

    init {
        isoDateFormat.timeZone = TimeZone.getTimeZone("GMT")
    }

    override fun findByServiceId(registryAddress: String, serviceId: String): List<TracingRecord> {
        val query = Query("$selectFields from \"$serviceId\" where rootId=tracingId", dataBase);
        val results = influxDB.query(query).results
        if (results.isEmpty() || results[0].series.isEmpty())
            return emptyList()
        val records = results[0].series[0].values.map { row ->
            buildRecord(row);
        }
        return records
    }

    override fun findByServiceIdAndRootId(registryAddress: String, serviceId: String, rootId: String): List<TracingRecord> {
        val query = Query("$selectFields from \"$serviceId\" where rootId='$rootId'", dataBase);
        val results = influxDB.query(query).results
        if (results.isEmpty() || results[0].series.isEmpty())
            return emptyList()
        val records = results[0].series[0].values.map { row ->
            buildRecord(row);
        }
        val sortedList = records.sortedBy { it.startTime }
        val recordsGroupByParentId = sortedList.groupBy { it.parentId ?: "root" }
        sortedList.forEach { record ->
            record.children = recordsGroupByParentId[record.tracingId]
        }
        return recordsGroupByParentId["root"]!!
    }

    override fun deleteByRootId(registryAddress: String, serviceId: String, rootId: String) {
        val query = Query("delete from $serviceId where rootId='$rootId'", dataBase);
        influxDB.query(query);
    }

    private fun buildRecord(row: List<Any>): TracingRecord {
        val record = TracingRecord();
        record.startTime = isoDateFormat.parse(row[0].toString()).time
        record.rootId = row[1].toString()
        record.parentId = row[2].toString()
        record.tracingId = row[3].toString()
        record.interfaceName = row[4].toString()
        record.methodName = row[5].toString()
        record.status = TracingRecord.STATUS.valueOf(row[6].toString())
        record.executionTime = (row[7] as Double).toLong()
        if(record.parentId!!.isEmpty())
            record.parentId = null
        return record;
    }
}